package com.fastplatform.specification;

import com.fastplatform.entity.Menu;
import com.fastplatform.entity.Menu_;
import com.fastplatform.entity.RoleMenu;
import com.fastplatform.entity.UserRole;
import org.springframework.data.jpa.domain.Specification;
import jakarta.persistence.criteria.*;
import java.util.ArrayList;
import java.util.List;

public class MenuSpecification {
    
    /**
     * 根据条件查找菜单列表（使用JPA Criteria Queries和元数据）
     */
    public static Specification<Menu> findMenusByConditions(String menuName, Integer menuType, Integer status) {
        return (root, query, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();
            
            // 基础条件：未删除
            predicates.add(criteriaBuilder.equal(root.get(Menu_.deleted), false));
            
            // 菜单名称模糊查询
            if (menuName != null && !menuName.trim().isEmpty()) {
                predicates.add(criteriaBuilder.like(root.get(Menu_.name), "%" + menuName + "%"));
            }
            
            // 菜单类型精确查询
            if (menuType != null) {
                predicates.add(criteriaBuilder.equal(root.get(Menu_.menuType), menuType));
            }
            
            // 状态精确查询
            if (status != null) {
                predicates.add(criteriaBuilder.equal(root.get(Menu_.status), status));
            }
            
            // 排序
            query.orderBy(criteriaBuilder.asc(root.get(Menu_.sort)));
            
            return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
        };
    }
    
    /**
     * 根据用户ID查找菜单列表（替代原生SQL查询）
     */
    public static Specification<Menu> findMenusByUserId(Long userId) {
        return (root, query, criteriaBuilder) -> {
            // 创建子查询获取用户角色的菜单ID
            Subquery<Long> menuIdSubquery = query.subquery(Long.class);
            Root<RoleMenu> roleMenuRoot = menuIdSubquery.from(RoleMenu.class);
            
            // 子查询：获取用户角色对应的菜单ID
            Subquery<Long> roleIdSubquery = menuIdSubquery.subquery(Long.class);
            Root<UserRole> userRoleRoot = roleIdSubquery.from(UserRole.class);
            roleIdSubquery.select(userRoleRoot.get("roleId"))
                         .where(
                             criteriaBuilder.and(
                                 criteriaBuilder.equal(userRoleRoot.get("userId"), userId),
                                 criteriaBuilder.equal(userRoleRoot.get("deleted"), false)
                             )
                         );
            
            menuIdSubquery.select(roleMenuRoot.get("menuId"))
                         .where(
                             criteriaBuilder.and(
                                 roleMenuRoot.get("roleId").in(roleIdSubquery),
                                 criteriaBuilder.equal(roleMenuRoot.get("deleted"), false)
                             )
                         );
            
            // 主查询条件
            List<Predicate> predicates = new ArrayList<>();
            predicates.add(criteriaBuilder.equal(root.get(Menu_.deleted), false));
            predicates.add(criteriaBuilder.equal(root.get(Menu_.status), 1));
            predicates.add(root.get(Menu_.id).in(menuIdSubquery));
            
            // 排序
            query.orderBy(criteriaBuilder.asc(root.get(Menu_.sort)));
            
            return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
        };
    }
    
    /**
     * 根据用户ID和菜单类型查找菜单列表（替代原生SQL查询）
     */
    public static Specification<Menu> findMenusByUserIdAndMenuType(Long userId, Integer menuType) {
        return (root, query, criteriaBuilder) -> {
            // 复用用户菜单查询逻辑
            Specification<Menu> userMenuSpec = findMenusByUserId(userId);
            Predicate userMenuPredicate = userMenuSpec.toPredicate(root, query, criteriaBuilder);
            
            // 添加菜单类型条件
            Predicate menuTypePredicate = criteriaBuilder.equal(root.get(Menu_.menuType), menuType);
            
            return criteriaBuilder.and(userMenuPredicate, menuTypePredicate);
        };
    }
    
    /**
     * 根据角色ID查找菜单列表（替代原生SQL查询）
     */
    public static Specification<Menu> findMenusByRoleId(Long roleId) {
        return (root, query, criteriaBuilder) -> {
            // 创建子查询获取角色的菜单ID
            Subquery<Long> menuIdSubquery = query.subquery(Long.class);
            Root<RoleMenu> roleMenuRoot = menuIdSubquery.from(RoleMenu.class);
            
            menuIdSubquery.select(roleMenuRoot.get("menuId"))
                         .where(
                             criteriaBuilder.and(
                                 criteriaBuilder.equal(roleMenuRoot.get("roleId"), roleId),
                                 criteriaBuilder.equal(roleMenuRoot.get("deleted"), false)
                             )
                         );
            
            // 主查询条件
            List<Predicate> predicates = new ArrayList<>();
            predicates.add(criteriaBuilder.equal(root.get(Menu_.deleted), false));
            predicates.add(criteriaBuilder.equal(root.get(Menu_.status), 1));
            predicates.add(root.get(Menu_.id).in(menuIdSubquery));
            
            // 排序
            query.orderBy(criteriaBuilder.asc(root.get(Menu_.sort)));
            
            return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
        };
    }
}